<template>
    <div id="taskSvg" class="hp100">
        <EditModal ref="editModal" :projectId="projectId" :contentId="contentId" @ok="handleOk"></EditModal>
        <DrawerPage v-model="reportModal.show" :title="reportModal.title" width="1000">
            <Summary :taskId="reportModal.taskId" v-if="reportModal.show"></Summary>
        </DrawerPage>
        <DetailModal ref="detailModal" :columns="columns"></DetailModal>
    </div>
</template>
<script>
    import * as d3 from "d3";
    import rootDefault from '@/assets/baseInfo/defult.jpg'
    import {
        queryTaskTree,
        delTask
    } from '../../api/task.js';
    import { showTimeNotSecond } from '@/libs/utils'
    import EditModal from './editTask.vue'
    import Summary from '../summary'
    import DetailModal from '../../detail';
    export default {
        name:'TaskAssign',
        components:{EditModal,Summary,DetailModal},
        data(){
            return {
                rootDefault,
                nodeSize:[240,50],
                taskNodeSize:[320,180],
                avatarSize:[60,60],
                accessGroupList:[],
                data:{},
                reportModal:{
                    show:false,
                    title:'科研文档'
                },
                gLink:[],
                gNode:[],
                columns:[
                    {
                        key:"taskName",
                        title:'任务名称',
                        tooltip:true
                    },
                    {
                        title: '任务状态',
                        key: 'status',
                        filter:(status) => {
                            return status === 0 ? '未开始' : status === 1 ? '已完成' : '进行中'
                        },
                        setColor: (status) => {
                            return status === 0 ? 'var(--status-pre)' : status === 1 ? 'var(--status-yes)' : 'var(--status-ing)'
                        },
                    },
                    {
                        title: '设备',
                        key: 'deviceTOS',
                        align: 'center',
                        minWidth:140,
                        filter:(deviceTOS) => deviceTOS.map(item => item.deviceName).join(','),
                        tooltip: true
                    },
                    {
                        key:"description",
                        title:'任务描述',
                        tooltip:true
                    },
                    {
                        key:"startTime",
                        title:'开始时间',
                        tooltip:true
                    },
                    {
                        key:"endTime",
                        title:'截止时间',
                        tooltip:true
                    },
                    {
                        key:"realTime",
                        title:'实际开始时间',
                        tooltip:true
                    },
                    {
                        key:"finishTime",
                        title:'完成时间',
                        tooltip:true
                    },
                    {
                        key:"createTime",
                        title:'创建时间',
                        tooltip:true
                    }
                ]
            }
        },
        computed:{
            contentDetail(){
                return this.detailParent.contentDetail
            },
            contentId(){
                return this.contentDetail.id
            },
            projectId(){
                return this.contentDetail.projectId
            },
            step(){
                return this.detailParent.step
            },
            disabledAllBtn(){
                return this.detailParent.disabledAllBtn
            },
        },
        inject:['detailParent'],
        watch:{
            step(val){
                this.drawNodes();
            }
        },
        mounted(){
            this.init()
        },
        methods:{
            getGroupList() {
                return new Promise((resolve,reject) => {
                    queryTaskTree(this.contentDetail.id).then((data) => {
                        if (data.code == 1) {
                            this.accessGroupList = data.data;
                            this.calcNodePos();
                            resolve()
                        } else if (data.code == -2) {
                            this.accessGroupList = [];
                            resolve()
                        } else {
                            this.$Message.warning(data.message);
                            resolve()
                        }
                    });
                })
            },
            calcNodePos(){
                let maxTask = 0;
                this.accessGroupList.forEach((group,index) => {
                    group.children = group.accessUserVOS;
                    group.accessUserVOS.forEach((item) => {
                        maxTask = Math.max(item.taskUserVOS.length,maxTask)
                        item.children = item.taskUserVOS.map((item,index) => {
                            return {
                                ...item,
                                index
                            }
                        })
                    })
                })
                this.data = {
                    ...this.root,
                    children:this.accessGroupList
                };
                this.maxTask = maxTask
            },
            async init(){
                await this.getGroupList();
                this.drawNodes()
            },
            handleOk(){
                this.init()
            },
            getMaxLevel(treeData,type,maxLevel=0,maxCol=0){
                if(!treeData || !treeData.length) return maxLevel
                    maxLevel ++;
                    maxCol ++;
                    (function getLevel(treeData,level=1,col=treeData.length){
                        if(maxCol < col){
                            maxCol = col
                        }
                        treeData.forEach(tree => {
                            tree.level = level;
                            if(maxLevel < level){
                                maxLevel = level;
                            }
                            if(tree.children && tree.children.length > 0){
                                getLevel(tree.children,level + 1,tree.children.length)
                            }
                        })
                    })(treeData)
                return type === 'level' ?  maxLevel : maxCol;
            },
            drawNodes(){
                d3.select("#taskSvg svg").remove();
                let width = this.$el.offsetWidth;
                let height = this.$el.offsetHeight;
                //定义边界
                const marge = {top:10, bottom:0, left:10, right:0};
                // 缩放和拖拽
                const zoom = d3
                .zoom()
                .extent([[0,0],[width,height]])
                .scaleExtent([0.5, 2])
                .on("zoom", ({transform}) => {
                    let g = d3.selectAll('.moveGroup');
                    g.attr('transform',transform)
                });
                this.svg = d3.select("#taskSvg").append('svg').attr('width',width).attr("height",height).call(zoom)
                let root = {x:width/2,y:10,text:`科研：${this.contentDetail.name}`,id:'root'};
                this.root = root;
                let data = d3.hierarchy(this.data)
                //tree
                let tree = d3.tree()
                .nodeSize(this.nodeSize);
                const nodes = tree(d3.hierarchy(this.data));
                let _this = this;
                function dealNodes(node){
                    node.x = node.x + width/2
                    node.y = node.y + _this.nodeSize[1] / 2
                    if(node.depth === 0){ //科研
                        _this.drawTextNode(_this.root)
                    }else if(node.depth === 1){ //组
                        _this.drawTextNode({x:node.x,y:node.y,text:`小组：${node.data.name}`})
                        _this.drawLine(node.parent,node)
                    }else if(node.depth === 2) { //组员
                        node.y = node.y + 20;
                        _this.drawUserNode({x:node.x,y:node.y,...node.data})
                        _this.drawLine(node.parent,node)
                        if(node.data.taskUserVOS){
                            node.data.taskUserVOS.forEach((task,index) => {
                                let data = {
                                    x:node.x + 30,
                                    y:node.y + (index * 200) + 80,
                                    ...task
                                }
                                _this.drawTaskNode(data,node.data)
                                _this.drawTaskLine(node,data)
                            })
                        }
                    }
                    node.children && node.children.forEach(node => {
                        dealNodes(node)
                    })
                }
                //线统一配置
                this.gLink = this.svg.append("g")
                .attr("fill", "none")
                .attr("stroke", "#a2a3a5")
                .attr("stroke-opacity",1)
                .attr("stroke-width", 1)
                .attr("class", `moveGroup lineMoveGroup`);
                // 节点统一配置
                this.gNode = this.svg.append("g")
                .attr("cursor", "pointer")
                .attr("pointer-events", "all")
                .attr("class", `moveGroup nodeMoveGroup`);
                dealNodes(nodes)
            },
            drawLine(node1,node2){
                this.gLink.append("line")
                .attr("x1", node1.x)
                .attr("y1", node1.y + 10)
                .attr("x2", node2.x)
                .attr("y2", node2.y - 10)
                .attr("stroke", "black")
                .attr("stroke-width", "1px")
                .style("stroke-dasharray","5,5")//dashed array for line 
            },
            drawTaskLine(node1,node2){
                let [imageWidth,imageHeight] = this.avatarSize;
                const path = d3.path();
                path.moveTo(node1.x,node1.y + imageHeight + 10)
                path.lineTo(node1.x,node2.y + imageHeight + 20)
                path.lineTo(node2.x,node2.y + imageHeight + 20)
                let line = this.gLink.append('path')
                    .attr('d',path)
                    .attr("stroke", "black")
                    .attr("fill", 'none')
                    .attr("stroke-width", "1px")
                    .style("stroke-dasharray","5,5")//dashed array for line 
            },
            drawUserNode(data){
                let [nodeWidth,nodeHeight] = this.nodeSize;
                const node = this.gNode.append("g")
                    // .attr("transform", d => `translate(${source.x0},${source.y0})`)
                    .attr("fill-opacity", 1)
                    .attr("stroke-opacity", 1)
                    .attr('class', 'userNode')
                    .attr('id', data.userId)
                node
                    .append('rect')
                    .attr('class','node-circle')
                    .attr('id',data.userId)
                    .attr('x', data.x - 30)
                    .attr('y', data.y)
                    .attr('width', 60)
                    .attr('height', 60)
                    .attr('fill','transparent')
                    .attr('rx', 30)
                    .attr('stroke', 'var(--default-color-level2)')//(d) => nodeColor(d.data)) //'rgb(246, 231, 111)'
                    .attr('stroke-width', 2);
                const fogt = node
                    .append('foreignObject')
                    .attr('x', data.x - 30)
                    .attr('y', data.y)
                    .attr('width', 60)
                    .attr('height', 60);
                fogt.append('xhtml:img')
                    .attr('src', (d) => {
                        let image_url = data.avatar || '';
                        const node_image = image_url ? `${image_url}` : this.rootDefault
                        return node_image;
                    })
                //     .attr('data-src',(d) => {
                //     if(d){
                //         return this.rootDefault
                //     }
                // })
                .attr('class','node-image')
                .attr('id', d => `node-image-${data.userId}`)
                .attr('width', 60)
                .attr('height',60)
                .style('border-radius','50%')
                .on('error', (event,d) => {
                    let img = event.srcElement;
                    img.src = this.rootDefault;
                    img.onerror = null;
                });
                //画名称
                node
                    .append('text')
                    .attr('dy',data.y + 20)
                    .attr('x',data.x + 40)
                    .attr('text-anchor','start')
                    .text(`昵称：${data.userName}`)
                    .style('fill','var(--default-color)')
                    .style('font-size',12)
                // 画操作   
                if(this.step === 0 && !this.disabledAllBtn){
                    node
                        .append('text')
                        .attr('dy', data.y + 40)
                        .attr('x',data.x + 40)
                        .attr('text-anchor', 'start')
                        .text('添加任务')
                        .style('fill','blue')
                        .style('font-size',12)
                        .style('cursor','pointer')
                        .on('click',(e) => {
                            this.currUser = data;
                            this.$refs.editModal.showModal('',data);
                        })
                    }
            },
            drawTextNode({x,y,text}){
                this.gNode.append("text") 
                .attr("x", x) 
                .attr("y", y) 
                .attr("dy", ".35em") 
                .style("text-anchor", "middle")
                .style("fill", 'var(--default-color)') 
                .text(text); 
            },
            drawTaskNode(data,user){
                console.log('task',data)
                let [nodeWidth,nodeHeight] = this.taskNodeSize;
                let padding = [14,7];
                let lineHeight = 22;
                let opSize = [44,24];
                const node = this.gNode.append("g")
                    // .attr("transform", d => `translate(${source.x0},${source.y0})`)
                    .attr("fill-opacity", 1)
                    .attr("stroke-opacity", 1)
                    .attr('class', 'userNode')
                    .attr('id', `task-node-${data.id}`)
                // 外框
                node
                    .append('rect')
                    .attr('class','node-circle')
                    .attr('x', data.x)
                    .attr('y', data.y)
                    .attr('width', nodeWidth)
                    .attr('height', nodeHeight)
                    .attr('fill','transparent')
                    .attr('rx', 5)
                    .attr('stroke', 'var(--default-color-level2)')//(d) => nodeColor(d.data)) //'rgb(246, 231, 111)'
                    .attr('stroke-width', 1)
                    .on('click',e => {
                        this.$refs.detailModal.showModal(data,data.taskName)
                    })
                //操作框
                if(this.step === 0 && data.status !== 0 && !this.disabledAllBtn){
                node
                    .append('rect')
                    .attr('class','node-circle')
                    .attr('x', data.x + nodeWidth - (opSize[0] + 10) * 2)
                    .attr('y', data.y)
                    .attr('width', opSize[0])
                    .attr('height',  opSize[1])
                    .attr('fill','transparent')
                    // .attr('rx', 5)
                    .attr('stroke', 'var(--operation-useable)')//(d) => nodeColor(d.data)) //'rgb(246, 231, 111)'
                    .attr('stroke-width', 1)
                    .style('cursor','pointer')
                    .on('click',(e) => {
                        this.currUser = data;
                        this.$refs.editModal.showModal(data,user);
                    })
                node
                    .append('text')
                    .attr('y',data.y + 7)
                    .attr('x',data.x + nodeWidth - (opSize[0] + 10) * 2)
                    .attr('dy',10)
                    .attr('dx',10)
                    .attr('text-anchor','start')
                    .text('修改')
                    .style('fill','var(--operation-useable)')
                    .style('cursor','pointer') //var(--default-color)
                    .style('font-size',12)
                    .on('click',(e) => {
                        this.currUser = data;
                        this.$refs.editModal.showModal(data,user);
                    })
                node
                    .append('rect')
                    .attr('class','node-circle')
                    .attr('id',data.userId)
                    .attr('x', data.x + nodeWidth - opSize[0] - 10)
                    .attr('y', data.y)
                    .attr('width', opSize[0])
                    .attr('height',  opSize[1])
                    .attr('fill','transparent')
                    .attr('rx', 0)
                    .attr('stroke', 'var(--operation-del)')
                    .style('cursor','pointer')
                    .attr('stroke-width', 1);
                node
                    .append('text')
                    .attr('y',data.y + 7)
                    .attr('x',data.x + nodeWidth - opSize[0] - 10)
                    .attr('dy',10)
                    .attr('dx',10)
                    .attr('text-anchor','start')
                    .text('删除')
                    .style('fill','var(--operation-del)')
                    .style('cursor','pointer') //var(--default-color)
                    .style('font-size',12)
                    .on('click',(e) => {
                        this.$Modal.confirm({
                            title: '确认删除？',
                            content: '<p></p>',
                            onOk: () => {
                                delTask(data.id).then(data => {
                                    this.init()
                                })
                            },
                            onCancel: () => {
                                
                            }
                        });
                    })
                }
                let devices = data.deviceTOS.map(item => item.deviceName).join(',');
                let textData = [
                     `任务名称：${data.taskName}`,
                     `任务描述：${data.description.length > 18 ? data.description.substring(0,18) + '...' : data.description || '-'}`,
                     `开始时间：${showTimeNotSecond(data.startTime) || '-'}`,
                     `截止时间：${showTimeNotSecond(data.endTime) || '-'}`,
                     `完成时间：${showTimeNotSecond(data.finishTime) || '-'}`,
                     `任务状态：${data.status === 0 ? '未开始' : data.status === 1 ? '已完成' : '进行中'}`,
                     `已分配设备：${devices.length > 18 ? devices.substring(0,18) + '...' : devices || '-'}`
                ]
                // console.log(data)
                textData.forEach((txt,index) => {
                    node
                        .append('text')
                        .attr('dy',data.y + padding[1] + (index + 1) * lineHeight)
                        .attr('x',data.x + padding[0])
                        .attr('text-anchor','start')
                        .text(txt)
                        .style('fill',index === 5 ? (data.status === 0 ? 'var(--status-pre)' : data.status === 1 ? 'var(--status-yes)' : 'var(--status-ing)') : 'var(--default-color)') //var(--default-color)
                        .style('font-size',12)
                })
                if(this.step === 1){
                    node
                        .append('rect')
                        .attr('class','node-circle')
                        .attr('id',data.userId)
                        .attr('x', data.x + nodeWidth - opSize[0] - padding[0])
                        .attr('y', data.y + nodeHeight - opSize[1] - padding[0])
                        .attr('width', opSize[0])
                        .attr('height',  opSize[1])
                        .attr('fill','transparent')
                        .attr('rx', 0)
                        .attr('stroke', 'var(--operation-useable)')
                        .style('cursor','pointer')
                        .attr('stroke-width', 1)
                        .on('click',(e) => {
                            this.reportModal.show = true;
                            this.reportModal.taskId = data.id;
                        })
                    node
                        .append('text')
                        .attr('y',data.y + nodeHeight - opSize[1] - padding[0] + 7)
                        .attr('x',data.x + nodeWidth - opSize[0] - padding[0])
                        .attr('dy',10)
                        .attr('dx',10)
                        .attr('text-anchor','start')
                        .text('文档')
                        .style('fill','var(--operation-useable)')
                        .style('cursor','pointer') //var(--default-color)
                        .style('font-size',12)
                        .on('click',(e) => {
                            this.reportModal.show = true;
                            this.reportModal.taskId = data.id;
                        })
                }
                // data.deviceTOS.forEach(device => {
                //     node
                //     .append('rect')
                //     .attr('class','node-circle')
                //     .attr('id',data.userId)
                //     .attr('x', data.x + nodeWidth - opSize[0])
                //     .attr('y', data.y)
                //     .attr('width', opSize[0])
                //     .attr('height',  opSize[1])
                //     .attr('fill','transparent')
                //     .attr('rx', 0)
                //     .attr('stroke', 'red')
                //     .style('cursor','pointer')
                //     .attr('stroke-width', 1);
                // node
                //     .append('text')
                //     .attr('y',data.y + 7)
                //     .attr('x',data.x + nodeWidth - opSize[0])
                //     .attr('dy',10)
                //     .attr('dx',10)
                //     .attr('text-anchor','start')
                //     .text(device.deviceName)
                //     .style('fill','red')
                //     .style('cursor','pointer') //var(--default-color)
                //     .style('font-size',12)
                //     .on('click',(e) => {
                //         this.$Modal.confirm({
                //             title: '确认删除？',
                //             content: '<p></p>',
                //             onOk: () => {
                //                 delTask(data.id).then(data => {
                //                     this.drawNodes()
                //                 })
                //             },
                //             onCancel: () => {
                                
                //             }
                //         });
                //     })
                // })
            }
        }
    }
</script>
<style scoped>
    .node-image {
        border-radius: 50%;
    }
</style>